require('./global');
const CFG = require("../config");

// ----------------------- 库函数定义 -----------------------
// 区分本地还是服务器
function isLocal()
{
  let isSrv = require("os").hostname().includes(CFG.RemoteHostKeyWord)
  return isSrv ? false : true;
}

//buf转成hex字符串
function buf2Hexstr(buf)
{
  let hexStr='';
  for(let i=0,len=buf.length;i<len;i++)
  {
    let n='00'+buf.readUInt8(i).toString(16);
    hexStr=hexStr+n.substr(-2)+' ';
  }
  return hexStr;
}

//求平均数
function arrAverage(arr)
{
  let sum=eval(arr.join("+"));
  return Number(sum/arr.length).toFixed(2);//   ~~(sum/arr.length*100)/100;//末尾保留两位小数
}

//求最大值
function arrMaxValue(arr)
{
  let max=-987654321;

  arr.some((one)=>{
    if(Number(one)>max) max=Number(one);
  })

  if(max==-987654321) console.log('arr error',arr);

  return Number(max).toFixed(2);//~~(max*100)/100;//末尾保留两位小数
}

//求最小值
function arrMinValue(arr)
{
  let min=987654321;

  arr.some((one)=>{
    if(Number(one)<min) min=Number(one);
  })

  return Number(min).toFixed(2);//~~(min*100)/100;//末尾保留两位小数
}

//打印输出object
function debugObject(resObj,level=0)
{
  let out='';

  Object.keys(resObj).some((key)=>{

    for(let i=0;i<level;i++) out += ' ';
    if(level>0) out += '-';
    out += key;

    if(typeof resObj[key] == 'object')//第二级仍然是对象
    {
      out += ':\r';
      out += debugObject(resObj[key],level+1);
    }
    else
    {
      out += ': '+resObj[key]+'\r';
    }
  })

  return out;
}

// 将一个ieee745标准的四字节（以整型存储），还原成浮点数返回
function ieee745_toFloat(data)
{
  const byte0 = (data >> 24) & 0xff;
  const byte1 = (data >> 16) & 0xff;
  const byte2 = (data >> 8) & 0xff;
  const byte3 = data & 0xff;
  const buf = Buffer.from([byte0, byte1, byte2, byte3]);
  return buf.readFloatBE(0);
}

// 将一个浮点数，以ieee745标准存成4字节，将此四字节以整型返回
function ieee745_floatSave(floatNum)
{
  const buf = Buffer.alloc(4);
  buf.writeFloatBE(floatNum, 0);
  return (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + buf[3];
}

// 无符号转有符号  65535 --> -1
function u16_to_s16(num)
{
  num &= 0xffff;
  if (num > 0x7fff) {
    return num - 0xffff - 1;
  }
  return num;
}

// 有符号转无符号  -1 --> 65535
function s16_to_u16(num)
{
  if (num >= 0) {
    if (num > 0x7fff) num &= 0x7fff;
    return num;
  } else if (num < 0) {
    num = 0 - num;
    if (num > 0x8000) num &= 0x7fff;
    num = 0x8000 - num;
    return num | 0x8000;
  }
  return num;
}

// 无符号转有符号
function u32_to_s32(num)
{
  num &= 0xffffffff;
  if (num > 0x7fffffff) {
    return num - 0xffffffff - 1;
  }
  return num;
}

// 有符号转无符号，貌似无用，因为天然的就是以u32存储的
function s32_to_u32(num)
{
  if (num >= 0) {
    if (num > 0x7fffffff) num &= 0x7fffffff;
    return num;
  } else if (num < 0) {
    num = 0 - num;
    if (num > 0x80000000) num &= 0x7fffffff;
    num = 0x80000000 - num;
    return num | 0x80000000;
  }
  return num;
}

//两个16进制的数进行相乘，输出16进制的结果
//输入和输出均为不带0x前缀的16进制字符串
//digits表示结果的位数
function hexMultiply(num1,num2,digits=8)
{
  let len1 = num1.length,
      len2 = num2.length;
  let pos = [];

  //j放外面，先固定被乘数的一位，分别去乘乘数的每一位，更符合竖式演算法
  for (let j = len2 - 1; j >= 0; j--) {
      for (let i = len1 - 1; i >= 0; i--) {
          //两个个位数相乘，最多产生两位数，index1代表十位，index2代表个位
          let index1 = i + j,
              index2 = i + j + 1;

          let a=parseInt(num1[i],16);
          let b=parseInt(num2[j],16);

          //两个个位数乘积加上当前位置个位已累积的数字，会产生进位，比如08 + 7 = 15，产生了进位1
          let mul = a * b + (pos[index2] || 0);
          //mul包含新计算的十位，加上原有的十位就是最新的十位
          pos[index1] = Math.floor(mul>>4) + (pos[index1] || 0);
          //mul的个位就是最新的个位
          pos[index2] = mul&0x0f;
      }
  }

  for(let i in pos) pos[i]=pos[i].toString(16);//每个位都转换为16进制数，比如10转a
  pos.splice(0,pos.length-digits);//只保留8位，即32bit

  return pos.join('') || '0';
}

//hwid转换为类型数值
function Hwid2TypeNum(Hwid)
{
  let DevTypeNum = 0;
  let DevGroup = parseInt(Hwid) >> 16;

  if(DevGroup && DevGroup<0x100) DevTypeNum = CFG.HwType.indexOf('wpass');
  else if(DevGroup >= 0x100 && DevGroup < 0x200) DevTypeNum = CFG.HwType.indexOf('gw');
  else if(DevGroup >= 0x300 && DevGroup < 0x500) DevTypeNum = CFG.HwType.indexOf('wdev');
  else if(DevGroup >= 0x1000 && DevGroup < 0x2000) DevTypeNum = CFG.HwType.indexOf('dtu');
  else DevTypeNum = 0;

  return DevTypeNum;
}

//id转换为类型字符串
function Hwid2TypeName(Hwid)
{
  let DevType = '';
  let DevGroup = Hwid >> 16;

  if(DevGroup && DevGroup < 0x100) DevType = CFG.T_Wpass;
  else if(DevGroup >= 0x100 && DevGroup < 0x200) DevType = CFG.T_Gw;
  else if(DevGroup >= 0x300 && DevGroup < 0x500) DevType = CFG.T_Wdev;
  else if(DevGroup >= 0x1000 && DevGroup < 0x2000) DevType = CFG.T_Dtu;
  else DevType = 'unkonw';

  return DevType;
}

//死循环延时
function SleepMs(ms) {
  var start = (new Date()).getTime();
  while ((new Date()).getTime() - start < ms) {
      // 使用  continue 实现；
      continue;
  }
}

//随机数生成器
function rand(Min,Max)
{
  let Range = Max - Min;
  let Rand = Math.random();
  return (Min + Math.round(Rand * Range));
}

// 数字截断补零
// 123456 变 3456
// 123 变 0123
function NumPadding(num, length)
{
  return (Array(length).join("0") + num).slice(-length);
}

// 拼接表名，将所有用户的表分散到数据库中
// 根据用户uid最后4位来确定数据表名
function CombTabName(uid, table)
{
  // 先检查有没有数字，避免弄成dat_json_0258_0258这种情况
  let array = table.split('_');
  if(array.length && isNum(array[array.length-1])) return table;

  // 拼接uid到table
  let name = [table, NumPadding(uid, 4)];
  return name.join('_');
}

// 全角转半角
function SBC_TO_DBC(str)
{
  const queue = {
    '０':'0','１':'1','２':'2','３':'3','４':'4','５':'5','６':'6','７':'7','８':'8','９':'9',
    'Ａ':'A','Ｂ':'B','Ｃ':'C','Ｄ':'D','Ｅ':'E','Ｆ':'F','Ｇ':'G','Ｈ':'H','Ｉ':'I','Ｊ':'J',
    'Ｋ':'K','Ｌ':'L','Ｍ':'M','Ｎ':'N','Ｏ':'O','Ｐ':'P','Ｑ':'Q','Ｒ':'R','Ｓ':'S','Ｔ':'T',
    'Ｕ':'U','Ｖ':'V','Ｗ':'W','Ｘ':'X','Ｙ':'Y','Ｚ':'Z','ａ':'a','ｂ':'b','ｃ':'c','ｄ':'d',
    'ｅ':'e','ｆ':'f','ｇ':'g','ｈ':'h','ｉ':'i','ｊ':'j','ｋ':'k','ｌ':'l','ｍ':'m','ｎ':'n',
    'ｏ':'o','ｐ':'p','ｑ':'q','ｒ':'r','ｓ':'s','ｔ':'t','ｕ':'u','ｖ':'v','ｗ':'w','ｘ':'x',
    'ｙ':'y','ｚ':'z',
    '－':'-','，':',','。':'.','：':':','（':'(','）':')','；':';',//替换列表结束
    ',_':'，','[.]_':'。',';_':'；',//本行为反向保留
  }

  for(c in queue){
    let regStr=new RegExp(c,'g');
    str = str.replace(regStr, queue[c]);
  }

  return str;
}

// 字符串转base64
function StringToBase64(str)
{
  return btoa(encodeURIComponent(str));
}

// base64转字符串
function Base64ToString(bStr)
{
  try {
    return decodeURIComponent(atob(bStr))
  } catch (error) {
    return '';
  }
}

// 从json键值对字符串里提取参数值，未成功 todo
function GetJsonValue(jsonStr,key)
{
  let res = jsonStr.match(/"'+key+'":"{1}([^"]*)"/g);
  return res;
}

// 为字符串添加转义斜杠
function AddSlashes(string)
{
  return string.replace(/\"/g, "\\\"");
  // string.replace(/\\/g, '\\').replace(/u0008/g, '\b').replace(/\t/g, '\t').
  //     replace(/\n/g, '\n').replace(/\f/g, '\f').replace(/\r/g, '\r').replace(/\'/g, '\'').
  //     replace(/\"/g, '\"');
}

exports.isLocal = isLocal;
exports.buf2Hexstr = buf2Hexstr;
exports.arrAverage = arrAverage;
exports.arrMaxValue = arrMaxValue;
exports.arrMinValue = arrMinValue;
exports.debugObject = debugObject;
exports.ieee745_toFloat = ieee745_toFloat;
exports.ieee745_floatSave = ieee745_floatSave;
exports.s16_to_u16 = s16_to_u16;
exports.u16_to_s16 = u16_to_s16;
exports.s32_to_u32 = s32_to_u32;
exports.u32_to_s32 = u32_to_s32;
exports.hexMultiply = hexMultiply;
exports.Hwid2TypeNum = Hwid2TypeNum;
exports.Hwid2TypeName = Hwid2TypeName;
exports.SleepMs = SleepMs;
exports.rand = rand;
exports.NumPadding = NumPadding;
exports.SBC_TO_DBC = SBC_TO_DBC;
exports.StringToBase64 = StringToBase64;
exports.Base64ToString = Base64ToString;
exports.GetJsonValue = GetJsonValue;
exports.AddSlashes = AddSlashes;
exports.CombTabName = CombTabName;